package com.ib.review.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ib.review.base.exception.ServiceException;
import com.ib.review.base.response.StatusCode;
import com.ib.review.base.utils.KnowledgeExcelReader;
import com.ib.review.pojo.bo.ExcelData;
import com.ib.review.pojo.bo.VectorBack;
import com.ib.review.pojo.dto.BatchDeleteParam;
import com.ib.review.pojo.dto.KnowledgeParam;
import com.ib.review.pojo.dto.KnowledgeQuery;
import com.ib.review.pojo.po.KnowledgeBasePO;
import com.ib.review.repository.KnowledgeRepository;
import com.ib.review.service.KnowledgeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

@Service
public class KnowledgeServiceImpl implements KnowledgeService {

    private KnowledgeRepository knowledgeRepository;
    @Autowired
    private void setKnowledgeRepository(KnowledgeRepository knowledgeRepository){
        this.knowledgeRepository = knowledgeRepository;
    }

    RestTemplate restTemplate = new RestTemplate();

    @Value("${vector.insert-url}")
    private String insertUrl;
    @Value("${vector.update-url}")
    private String updateUrl;
    @Value("${vector.delete-url}")
    private String deleteUrl;

    public Page<KnowledgeBasePO> query(KnowledgeQuery knowledgeQuery) {
        return knowledgeRepository.query(knowledgeQuery);
    }

    public void add(KnowledgeParam knowledgeParam) {

        knowledgeParam.setType(knowledgeParam.getType() == null ? 1 : knowledgeParam.getType());
        Integer count = knowledgeRepository.selectCountByName(knowledgeParam);
        if (count > 0) {
            throw new ServiceException(StatusCode.KNOWLEDGE_NAME_EXIST);
        }
        // 取反再校验（存在相反则覆盖-做修改操作）
        KnowledgeParam paramQuery = new KnowledgeParam();
        BeanUtils.copyProperties(knowledgeParam,paramQuery);
        if (knowledgeParam.getType() == 1) {
            paramQuery.setType(2);
        } else {
            paramQuery.setType(1);
        }
        String userName = StpUtil.getTokenSession().getString("userAccount");
        KnowledgeBasePO queryPO = knowledgeRepository.queryByName(paramQuery);
        if (queryPO != null) {
            // 执行修改操作
            Map<String, Object> paramBody3 = new HashMap<>();
            paramBody3.put("knowledgeName", knowledgeParam.getKnowledgeName());
            paramBody3.put("knowledgeSynonym", knowledgeParam.getKnowledgeSynonym());
            paramBody3.put("type", knowledgeParam.getType());
            VectorUpdate(paramBody3,queryPO.getKnowledgeId());

            KnowledgeBasePO po3 = new KnowledgeBasePO();
            po3.setKnowledgeId(queryPO.getKnowledgeId());
            po3.setKnowledgeName(knowledgeParam.getKnowledgeName());
            po3.setKnowledgeSynonym(knowledgeParam.getKnowledgeSynonym());
            po3.setKnowledgeDesc(knowledgeParam.getKnowledgeDesc());
            po3.setType(knowledgeParam.getType());
            po3.setModifier(userName);
            po3.setModifyTime(getCurrentDateWithoutMillis());
            knowledgeRepository.edit(po3);
            return;
        }
        // 存入向量库
        Map<String, Object> paramBody = new HashMap<>();
        paramBody.put("knowledgeName", knowledgeParam.getKnowledgeName());
        paramBody.put("knowledgeSynonym", knowledgeParam.getKnowledgeSynonym());
        paramBody.put("type", knowledgeParam.getType());

        VectorBack vectorBack = VectorInsert(paramBody);
        Map<String,String> data = vectorBack.getData();

        KnowledgeBasePO po = new KnowledgeBasePO();
        BeanUtils.copyProperties(knowledgeParam,po);
        Date currentDate = getCurrentDateWithoutMillis();
        String uuid = data.get("id");
        po.setKnowledgeId(uuid);
        po.setCreator(userName);
        po.setCreateTime(currentDate);
        po.setModifier(userName);
        po.setModifyTime(currentDate);
        po.setType(knowledgeParam.getType());
        po.setDelFlag(0);
        knowledgeRepository.add(po);
    }

    public void delete(KnowledgeParam knowledgeParam) {

        List<String> ids = new ArrayList<>();
        ids.add(knowledgeParam.getKnowledgeId());
        VectorDelete(ids);

        knowledgeRepository.delete(knowledgeParam.getKnowledgeId());
    }

    public void edit(KnowledgeParam knowledgeParam) {
        // 更新向量库
        Map<String, Object> paramBody2 = new HashMap<>();
        paramBody2.put("knowledgeName", knowledgeParam.getKnowledgeName());
        paramBody2.put("knowledgeSynonym", knowledgeParam.getKnowledgeSynonym());
        paramBody2.put("type", 1);
        VectorUpdate(paramBody2,knowledgeParam.getKnowledgeId());
        // 更新数据库
        String userName = StpUtil.getTokenSession().getString("userAccount");
        KnowledgeBasePO po5 = new KnowledgeBasePO();
        BeanUtils.copyProperties(knowledgeParam,po5);
        po5.setModifier(userName);
        po5.setModifyTime(getCurrentDateWithoutMillis());
        knowledgeRepository.edit(po5);
    }

    public void batchDelete(BatchDeleteParam batchDeleteParam) {
        List<String> list = batchDeleteParam.getIds();
        if (!list.isEmpty()) {
            VectorDelete(list);
            knowledgeRepository.batchDelete(list);
        }
    }

    public void importExcel(MultipartFile file) {
        if (!isExcelFile(file)) {
            throw new ServiceException(StatusCode.EXCEL_ERROR);
        }
        String userName = StpUtil.getTokenSession().getString("userAccount");
        List<KnowledgeBasePO> list = new ArrayList<>();

        List<ExcelData> data;
        try {
            data = KnowledgeExcelReader.readExcel(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        List<KnowledgeBasePO> list3 = new ArrayList<>();
        for (ExcelData excelData : data) {
            KnowledgeParam param = new KnowledgeParam();
            BeanUtils.copyProperties(excelData, param);
            param.setType(1);
            Integer count = knowledgeRepository.selectCountByName(param);
            if (count > 0) {
                continue;
            }
            param.setType(2);
            KnowledgeBasePO queryPO = knowledgeRepository.queryByName(param);
            if (queryPO != null) {
                queryPO.setKnowledgeName(excelData.getKnowledgeName());
                queryPO.setKnowledgeSynonym(excelData.getKnowledgeSynonym());
                queryPO.setKnowledgeDesc(excelData.getKnowledgeDesc());
                list3.add(queryPO);
                continue;
            }
            // 存入向量库
            Map<String, Object> paramBody = new HashMap<>();
            paramBody.put("knowledgeName", excelData.getKnowledgeName());
            paramBody.put("knowledgeSynonym", excelData.getKnowledgeSynonym());
            paramBody.put("type", 1);

            VectorBack vectorBack = VectorInsert(paramBody);

            Map<String,String> data2 = vectorBack.getData();
            String uuid = data2.get("id");

            KnowledgeBasePO po = new KnowledgeBasePO();
            BeanUtils.copyProperties(excelData, po);
            Date currentDate = getCurrentDateWithoutMillis();
            po.setKnowledgeId(uuid);
            po.setType(1);
            po.setCreator(userName);
            po.setCreateTime(currentDate);
            po.setModifier(userName);
            po.setModifyTime(currentDate);
            po.setDelFlag(0);
            list.add(po);
        }
        // 批量插入
        knowledgeRepository.batchInsert(list);

        for (KnowledgeBasePO po : list3) {
            // 批量修改
            Map<String, Object> paramBody1 = new HashMap<>();
            paramBody1.put("knowledgeName", po.getKnowledgeName());
            paramBody1.put("knowledgeSynonym", po.getKnowledgeSynonym());
            paramBody1.put("type", 1);
            VectorUpdate(paramBody1,po.getKnowledgeId());
            po.setModifier(userName);
            po.setModifyTime(getCurrentDateWithoutMillis());
            knowledgeRepository.edit(po);
        }
    }

    private Date getCurrentDateWithoutMillis() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        return Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
    }

    private boolean isExcelFile(MultipartFile file) {

        // 验证文件类型（Excel）
        String contentType = file.getContentType();
        String originalFilename = file.getOriginalFilename();

        // 允许的Excel扩展名
        List<String> allowedExtensions = Arrays.asList(".xls", ".xlsx");
        // 允许的Excel MIME类型
        List<String> allowedContentTypes = Arrays.asList(
                "application/vnd.ms-excel", // .xls
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xlsx
                "application/octet-stream" // 某些浏览器可能返回的通用二进制类型
        );

        // 验证扩展名
        boolean extensionValid = false;
        if(originalFilename != null) {
            extensionValid = allowedExtensions.stream()
                    .anyMatch(ext -> originalFilename.toLowerCase().endsWith(ext));
        }

        // 验证Content-Type
        boolean contentTypeValid = allowedContentTypes.contains(contentType);

        return extensionValid && contentTypeValid;
    }

    private VectorBack VectorInsert(Map<String, Object> body) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("text", body.get("knowledgeName"));
        requestBody.put("metadata", body);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 构建请求实体
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        // 发送请求
        ResponseEntity<VectorBack> response = restTemplate.exchange(
                insertUrl,
                HttpMethod.POST,
                requestEntity,
                VectorBack.class
        );
        return response.getBody();
    }

    private void VectorUpdate(Map<String, Object> body,String knowledgeId) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("text", body.get("knowledgeName"));
        requestBody.put("metadata", body);
        requestBody.put("id", knowledgeId);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 构建请求实体
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        // 发送请求
        restTemplate.exchange(updateUrl,HttpMethod.POST,requestEntity,VectorBack.class);
    }

    private void VectorDelete(List<String> body) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("ids", body);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 构建请求实体
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        // 发送请求
        restTemplate.exchange(deleteUrl,HttpMethod.POST,requestEntity,VectorBack.class);
    }
}
